package com.gqr.deadlock;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;

/**
 * Copyright (C), 2020-2024,gqr
 * FileName:ThreadMXBeanDetection
 * author:guqingrong
 * Date:2024-05-04 20:18
 * Description:用ThreadMXBean检测死锁
 * History:
 * <author>    <time>    <version>    <desc>
 * 作者姓名     修改时间     版本号        描述
 */
public class ThreadMXBeanDetection implements Runnable{

    int flag = 1;
    static Object o1 = new Object();
    static Object o2 = new Object();

    public static void main(String[] args) throws InterruptedException {
        ThreadMXBeanDetection r1 = new ThreadMXBeanDetection();
        ThreadMXBeanDetection r2 = new ThreadMXBeanDetection();
        r1.flag=1;
        r2.flag=0;

        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r2);
        t1.start();
        t2.start();
        Thread.sleep(1000);
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        long[] deadlockedThreads = threadMXBean.findDeadlockedThreads();
        if(deadlockedThreads!=null && deadlockedThreads.length>0){
            for (int i = 0; i < deadlockedThreads.length; i++) {
                ThreadInfo threadInfo = threadMXBean.getThreadInfo(deadlockedThreads[i]);
                System.out.println("发现死锁了"+threadInfo.getThreadName());
                //  记录日志 重启程序 报警 等等实际需要的机制
            }
        }
    }

    @Override
    public void run() {
        System.out.println("flag = " + flag);
        /**
         * 当类的对象flag=1时(T1),先锁定o1,睡眠500毫秒,然后去锁定o2
         * 而T1在睡眠的时候另一个flag=0的对象(T2)线程启动,先锁定o2,睡眠500毫秒,等待T1释放o1
         * T1睡眠结束后需要锁定o2才能继续执行,而此时o2已被T2锁定
         * T2睡眠结束后需要锁定o1才能继续执行,而此时o1已被t1锁定
         * T1,T2相互等待,都需要对方锁定的资源才能继续执行,从而死锁
         */
        if (flag == 1) {
            synchronized (o1){
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (o2){
                    System.out.println("线程1成功拿到了2把锁");
                }
            }
        }
        if (flag == 0) {
            synchronized (o2){
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (o1){
                    System.out.println("线程2成功拿到了2把锁");
                }
            }
        }
    }
}
